<template>
  <Dialog
    ref="dialog"
    :closed="!options.show"
    :modal="options.modal"
    :title="options.title"
    :closable="options.closeable"
    :dialogStyle="dialogStyle"
    @close="closeEvent"
    @open="openEvent"
    v-bind="options.attributes"
    v-on="options.events"
  >
    <template #header>
      <slot name="header">
        <span class="panel-title">{{ options.title }}</span>
      </slot>
    </template>

    <ArkScroll>
      <slot></slot>
    </ArkScroll>

    <div
      class="dialog-button !sticky bottom-0 right-0 left-0"
      v-if="options.footer?.show"
    >
      <slot name="footer">
        <LinkButton
          iconCls="icon-clear"
          v-if="showButton(options.footer.cancel)"
          :disabled="disabledButton(options.footer.cancel)"
          @click="clickButton(options.footer.cancel)"
        >
          {{
            options.footer.cancel?.text ? options.footer.cancel?.text : "取消"
          }}
        </LinkButton>

        <LinkButton
          iconCls="icon-save"
          v-if="showButton(options.footer.confirm)"
          :disabled="disabledButton(options.footer.confirm)"
          @click="clickButton(options.footer.confirm)"
        >
          {{
            options.footer.confirm?.text ? options.footer.confirm?.text : "确定"
          }}
        </LinkButton>
      </slot>
    </div>
  </Dialog>
</template>

<script setup lang="ts">
import {computed, onBeforeMount, type PropType, useTemplateRef, watch} from "vue";
import _ from "lodash";
import ArkDialogOptionsDefault, {ArkDialogOptions} from "./ArkDialogOptions";
import {ArkActionButton} from "../../common-type/ark-action-button";
import ArkScroll from "../../basic/ark-scroll/ArkScroll.vue";

/** 接口（组件的接口）。包括：defineOptions、defineModel、defineProps、defineEmits、defineExpose、defineSlots */
const options = defineModel("options", {
  type: Object as PropType<ArkDialogOptions>,
  default: () => ArkDialogOptionsDefault
});

/** 本地状态 (本地的响应式 property)。包括：ref、computed */
const dialogRef = useTemplateRef("dialog");

const dialogStyle = computed(() => {
  const result: Record<string, any> = {
    "max-height": "100%",
    // 由于该dialog有个1px的边框，当设置为width：100%时，由于总宽度超出，dialog会被置于下一页，因此设置最大宽度为减 1px
    "max-width": "calc(100% - 1px)",
  };

  const width = options.value.width;
  if (!_.isNil(width)) {
    if (typeof width === "number") {
      result.width = `${width}px`;
    } else {
      result.width = width;
    }
  }
  const height = options.value.height;
  if (!_.isNil(height)) {
    if (typeof height === "number") {
      result.height = `${height}px`;
    } else {
      result.height = height;
    }
  }

  if (options.value.fullscreen) {
    result.left = 0;
    result.right = 0;
    result.top = 0;
    result.bottom = 0;
  }

  return result;
});

/** 事件（通过响应式事件触发的回调）。包括：watch */
watch(
  () => {
    return options.value.show;
  },
  () => {
    if (options.value.show) {
      dialogRef.value?.open();
    } else {
      dialogRef.value?.close();
    }
  },
);

/** 生命周期钩子（按照它们被调用的顺序）。包括：onBeforeMount、onMounted、onBeforeUpdate、onUpdated、onBeforeUnmount、onUnmounted */
onBeforeMount(() => {
  init();
});

/** 非响应式的 property (不依赖响应系统的实例 property)。包括：常规函数 */
const init = () => {
  _.defaultsDeep(options.value, ArkDialogOptionsDefault);
};

const openEvent = () => {
  options.value.show = true;
};
const closeEvent = async () => {
  const onClose = options.value.onClose;

  if (_.isNil(onClose)) {
    options.value.show = false;
    return;
  }

  const result = onClose();
  if (_.isNil(result)) {
    options.value.show = false;
    return;
  }

  if (typeof result === "boolean") {
    if (result) {
      options.value.show = false;
    }
  } else {
    await Promise.resolve(result);
    options.value.show = false;
  }
};

const showButton = (buttonObj: ArkActionButton<any>) => {
  if (_.isNil(buttonObj)) {
    return true;
  }

  if (_.isNil(buttonObj.show)) {
    return true;
  }

  return buttonObj.show;
};
const disabledButton = (buttonObj: ArkActionButton<any>) => {
  if (_.isNil(buttonObj)) {
    return false;
  }

  if (_.isNil(buttonObj.show)) {
    return false;
  }

  return buttonObj.disabled;
};
const clickButton = async (buttonObj: ArkActionButton<any>) => {
  if (_.isNil(buttonObj)) {
    return;
  }

  if (disabledButton(buttonObj)) {
    return;
  }

  if (typeof buttonObj.beforeClick === "function") {
    const beforeClickReturnVal = buttonObj.beforeClick();
    if (!_.isNil(beforeClickReturnVal)) {
      if (typeof beforeClickReturnVal === "boolean" && !beforeClickReturnVal) {
        return;
      }

      await beforeClickReturnVal;
    }
  }

  if (!_.isNil(buttonObj.onClick)) {
    const returnVal = buttonObj.onClick();

    if (!_.isNil(buttonObj.afterClick)) {
      buttonObj.afterClick(returnVal);
    }

    if (_.isNil(returnVal)) {
      options.value.show = false;
      return;
    }

    if (typeof returnVal === "boolean") {
      if (returnVal) {
        options.value.show = false;
      }
      return;
    }

    await returnVal;
    options.value.show = false;
    return;
  }

  if (!_.isNil(buttonObj.afterClick)) {
    buttonObj.afterClick();
  }
};

/** 其它 */
</script>

<style scoped lang="scss">
.app-dialog {
  max-height: 100%;
}
</style>
